import 'dart:convert';

import 'package:baselib/utils/log_util.dart';
import 'package:baselib/utils/sp_util.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:framelib/config/app_config.dart';
import 'package:framelib/net/base_entity.dart';
import 'package:framelib/net/interceptor.dart';
import 'package:framelib/utils/constant_util.dart';

import 'errorhandle.dart';

enum METHODTYPE {

  GET(name: 'GET',value: 'GET'),
  POST(name: 'POST',value: 'POST'),
  PUT(name: 'PUT',value: 'PUT'),
  DELETE(name: 'DELETE',value: 'DELETE');

  final String name;
  final String value;

  const METHODTYPE({required this.name,required this.value});
}
class DioUtil{

  static final DioUtil _singleton = DioUtil._internal();

  static DioUtil get instance => DioUtil();

  factory DioUtil(){
    return _singleton;
  }

  static Dio? _dio;
  static Dio? get dio => _dio;
  String _baseUrl = AppConfig.instance.baseUrl;
  DioUtil._internal() {
    var baseOptions = BaseOptions(
      connectTimeout: Duration(seconds: 5),
      receiveTimeout: Duration(seconds: 5),
      responseType: ResponseType.json,
      validateStatus: (status){
        return true;
      },
      baseUrl: _baseUrl
    );
    _dio = Dio(baseOptions);
    if(kDebugMode)_dio!.interceptors.add(LoggingInterceptor());
    _dio!.interceptors.add(AdapterInterceptor());
  }
  //初始化dio
  initDio({String? baseUrl}){
    _baseUrl=baseUrl??'';
  }

  //添加拦截器
  DioUtil addInterceptor({Interceptor? interceptor}){
    if(interceptor!=null)_dio?.interceptors?.add(interceptor);
    return this;
  }
  //切换baseUrl
  DioUtil setBaseUrl({String? baseUrl,bool? isTempUseCurSetBaseUrl}){
    if(isTempUseCurSetBaseUrl??false){
      _dio?.options?.baseUrl = baseUrl??'';
    }else{
      _dio?.options?.baseUrl=baseUrl??_baseUrl;
    }
    return this;
  }

  Future<BaseEntity> request(
      String url, {
      METHODTYPE? methodtype,
      dynamic data,
      Map<String, dynamic>? queryParameters,
        bool? isFormData,
        List<MultipartFile>?  multipartFiles,
        CancelToken? cancelToken,
        List<Map<String,dynamic>>? addHeaders,
      ProgressCallback? onSendProgress,
      ProgressCallback? onReceiveProgress,
        bool? isReturnAll
  }) async{
   FormData? formData;
   if((isFormData??false)){
     formData = FormData.fromMap(data??{});
     if((multipartFiles??[]).isNotEmpty){
       multipartFiles!.forEach((element){
         formData!.files.add(MapEntry('files', element));
       });
     }
   }
   try{
     Response? response = await _dio?.request(
       url,
       data: (isFormData??false)?formData:data,
       queryParameters: queryParameters,
       options: _checkOptions(methodtype,addHeaders)
     );
     var responseData = response?.data;
     int? code = Errorhandle.success;
     String? msg = '';
     var resultData;
     LogUtil.d('request--->get response?.statusCode=${response?.statusCode}');
     LogUtil.d('request--->get response?.statusMessage=${response?.statusMessage}');
     LogUtil.d('request--->get response?.data=${response?.data}');
     LogUtil.d('request--->get response?.data is Map=${response?.data is Map}');
     if(response?.statusCode!=Errorhandle.success){
       code = response?.statusCode;
       msg = response?.statusMessage;
       if(responseData!=null&&(responseData is Map)){
         code = responseData['code'];
         msg = responseData['msg'];
       }
     }else{
       if(isReturnAll??false){
         resultData = responseData;
       }else{
         if(responseData!=null&&(responseData is Map)){
           LogUtil.d('request--->get responseData is Map=${responseData is Map},responseData=$responseData');
           code = responseData['code'];
           msg = responseData['msg'];
           resultData = responseData['data'];
         } else {
           LogUtil.d('request--->get responseData not Map=${responseData is Map},responseData=$responseData');
           resultData = responseData;
         }
       }
     }
     // LogUtil.d('request--->get code=${code},msg=${msg},data=${resultData},');
     return BaseEntity(code: code, msg: msg, data: resultData);
   }catch(e){
     var handleError = Errorhandle.handleError(e);
     return BaseEntity(code: handleError.status, msg: handleError.message, data: null);
   }
  }

  Options _checkOptions(METHODTYPE? methodtype, List<Map<String,dynamic>>? addHeaders) {
    Options options = Options(headers: {});
    if((addHeaders??[]).isNotEmpty){
      addHeaders?.forEach((element) {
        options.headers!.addAll(element);
      });
    }
    options.method = (methodtype??METHODTYPE.GET).value;
    return options;
  }
}